﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace ASPNETPerformance.App_BusinessLogic.PageFilter {
    public class NamingContainerFilterCS : Stream {
        private Stream responseStream;

        StringBuilder sbBuffer;

        public NamingContainerFilterCS( Stream stream ) {
            responseStream = stream;

            sbBuffer = new StringBuilder();
        }

        public override void Write( byte[] buffer, int offset, int count ) {
            string strBuffer = Encoding.UTF8.GetString( buffer, offset, count );

            if ( strBuffer.IndexOf( "</form>", StringComparison.InvariantCultureIgnoreCase ) >= 0 ||
                strBuffer.IndexOf( "</html>", StringComparison.InvariantCultureIgnoreCase ) >= 0 ) {
                sbBuffer.Append( strBuffer );

                byte[] data = Encoding.UTF8.GetBytes( StripNamingContainer( sbBuffer.ToString() ) );

                responseStream.Write( data, 0, data.Length );

                sbBuffer.Length = 0;
            }
            else {
                sbBuffer.Append( strBuffer );
            }
        }

        private string StripNamingContainer( string strHTML ) {
            RegexOptions opt =
                RegexOptions.IgnoreCase |
                RegexOptions.Singleline |
                RegexOptions.CultureInvariant |
                RegexOptions.Compiled;

            Regex re = new Regex( "( name=\")(?=.*(" + Regex.Escape( "$" ) + "))([^\"]+?)(\")", opt );

            strHTML = re.Replace( strHTML, new MatchEvaluator( delegate( Match m ) {
                int lastDollarSignIndex = m.Value.LastIndexOf( '$' );

                if ( lastDollarSignIndex >= 0 ) {
                    return m.Groups[ 1 ].Value + m.Value.Substring( lastDollarSignIndex + 1 );
                }
                else {
                    return m.Value;
                }
            } ) );

            return strHTML;
        }

        public override bool CanRead {
            get {
                return true;
            }
        }

        public override bool CanSeek {
            get {
                return true;
            }
        }

        public override bool CanWrite {
            get {
                return true;
            }
        }

        public override void Flush() {
            responseStream.Flush();
        }

        public override long Length {
            get {
                return responseStream.Length;
            }
        }

        long position;

        public override long Position {
            get {
                return position;
            }
            set {
                position = value;
            }
        }

        public override int Read( byte[] buffer, int offset, int count ) {
            return responseStream.Read( buffer, offset, count );
        }

        public override long Seek( long offset, SeekOrigin origin ) {
            return responseStream.Seek( offset, origin );
        }

        public override void SetLength( long value ) {
            responseStream.SetLength( value );
        }

        public override void Close() {
            responseStream.Close();
        }
    }
}
